Android Touch事件传递机制(二) 您所在的位置:网站首页 android ontouch Android Touch事件传递机制(二)

Android Touch事件传递机制(二)

2024-07-17 00:04| 来源: 网络整理| 查看: 265

(本文基于android-2.3.3_r1代码研究)

在Android Touch事件传递机制(一) – onInterceptTouchEvent & onTouchEvent这篇文章中研究了Android触屏事件的分发机制;本文继续深入研究。

OnTouchListener & onTouchEvent

首先我们来看看View的OnTouchListener与onTouchEvent方法的区别与联系,如下布局:

设置OnTouchListener:

MyView view = (MyView) findViewById(R.id.my_view); view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { boolean ret = false; Log.e("Test5Activity", "onTouch:" + ret + " action:" + TouchUtil.actionToString(event.getAction())); return ret; } });

运行demo,在MyView上按下触屏并滑动后松开,查看log:

E/Test5Activity﹕ onTouch:false action:ACTION_DOWN E/MyView﹕ onTouchEvent:false action:ACTION_DOWN

可以看到,设置了OnTouchListener后,MyView收到down事件后首先回调OnTouchListener的onTouch方法,然后才会将down事件分发给MyView的onTouchEvent方法处理;由于onTouchEvent方法返回false,后续事件将不再分发给MyView。

onTouch方法默认返回false。那么我们返回true再运行一次试试:

E/Test5Activity﹕ onTouch:true action:ACTION_DOWN E/Test5Activity﹕ onTouch:true action:ACTION_MOVE E/Test5Activity﹕ onTouch:true action:ACTION_MOVE ...... E/Test5Activity﹕ onTouch:true action:ACTION_MOVE E/Test5Activity﹕ onTouch:true action:ACTION_UP

可以看到,当onTouch方法返回true时,MyView的touch事件将不再分发给其onTouchEvent方法。我们看下OnTouchListener和onTouch的解释:

/** * Interface definition for a callback to be invoked when a touch event is * dispatched to this view. The callback will be invoked before the touch * event is given to the view. */ public interface OnTouchListener { /** * Called when a touch event is dispatched to a view. This allows listeners to * get a chance to respond before the target view. * * @param v The view the touch event has been dispatched to. * @param event The MotionEvent object containing full information about * the event. * @return True if the listener has consumed the event, false otherwise. */ boolean onTouch(View v, MotionEvent event); }

设置OnTouchListener回调之后,touch事件在分发给view之后,我们将有机会在目标view之前对这个touch事件进行响应;

onTouch方法返回true表示这个touch事件已被消费掉,这就意味着touch事件不会再继续分发给目标view。

OnTouchListener & OnClickListener

对MyView设置OnTouchListener 和 OnClickListener,onTouch方法返回false:

MyView view = (MyView) findViewById(R.id.my_view); view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { boolean ret; ret = false; // ret = true; Log.e("Test5Activity", "onTouch:" + ret + " action:" + TouchUtil.actionToString(event.getAction())); return ret; } }); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("Test5Activity", "onClick"); } });

在按钮上按下触屏、移动、放开触屏,查看log:

E/Test5Activity﹕ onTouch:false action:ACTION_DOWN E/MyView﹕ onTouchEvent:true action:ACTION_DOWN E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/MyView﹕ onTouchEvent:true action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/MyView﹕ onTouchEvent:true action:ACTION_MOVE ...... E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/MyView﹕ onTouchEvent:true action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_UP E/MyView﹕ onTouchEvent:true action:ACTION_UP E/Test5Activity﹕ onClick

可以看到,onTouch方法被调用了多次,分别对应了按下(ACTION_DOWN)、移动(ACTION_MOVE)、松开(ACTION_UP)等事件;onClick事件发生在ACTION_UP之后,只回调一次。

onTouch方法返回true再看下log:

08-20 01:25:18.056: E/TouchTest(658): onTouch -> ACTION_DOWN 08-20 01:25:18.065: E/TouchTest(658): onTouch -> ACTION_MOVE 08-20 01:25:18.100: E/TouchTest(658): onTouch -> ACTION_MOVE 08-20 01:25:18.446: E/TouchTest(658): onTouch -> ACTION_MOVE 08-20 01:25:18.508: E/TouchTest(658): onTouch -> ACTION_MOVE 08-20 01:25:18.656: E/TouchTest(658): onTouch -> ACTION_UP

可以看到,onClick方法不再被调用。这是因为在touch事件分发给onClick方法之前,被onTouch方法拦截并消费掉,因此不再分发给onClick方法。

#OnLongClickListener

再来看看OnLongClickListener与OnTouchListener 和 OnClickListener的调用时序关系。

先看下OnLongClickListener的注释:

/** * Interface definition for a callback to be invoked when a view has been clicked and held. */ public interface OnLongClickListener { /** * Called when a view has been clicked and held. * * @param v The view that was clicked and held. * * @return true if the callback consumed the long click, false otherwise. */ boolean onLongClick(View v); }

OnLongClickListener接口定义了长按触屏的回调,当我们在一个view上点击并保持一段时间后,就会唤起这个回调。onLongClick返回true表示已经消费了这次长按,否则返回false。

给MyView设置OnLongClickListener,onLongClick方法默认返回false:

view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { boolean ret; ret = false; // ret = true; Log.e("Test5Activity", "onLongClick:" + ret); return ret; } });

在MyView上按下触屏并滑动,一段时间后松开触屏:

E/Test5Activity﹕ onTouch:false action:ACTION_DOWN E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_MOVE ...... E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onLongClick:false E/Test5Activity﹕ onTouch:false action:ACTION_MOVE ...... E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_UP E/Test5Activity﹕ onClick

可以看出,onClick在触屏抬起后触发;onLongClick方法在触屏抬起前触发,并需要手指按下超过一定时间;滑动手指不影响点击与长按事件的触发。

onLongClick方法返回true再看下:

E/Test5Activity﹕ onTouch:false action:ACTION_DOWN E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_MOVE ...... E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onLongClick:true E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_MOVE ...... E/Test5Activity﹕ onTouch:false action:ACTION_MOVE E/Test5Activity﹕ onTouch:false action:ACTION_UP

可以看到,onLongClick方法返回true后,onClick方法就不再触发了,这是因为onLongClick消费了长按事件。

总结

设置OnTouchListener:onTouch方法返回false时,onTouch方法及View的onTouchEvent方法依次被调用;onTouch方法返回true时,只调用onTouch方法,onTouchEvent方法不再被调用

设置OnTouchListener后:onTouch方法返回false,不影响OnClickListener及OnLongClickListener的触发;onTouch方法返回true时,OnClickListener及OnLongClickListener不再触发

OnClickListener的触发条件是手指从触屏抬起;OnLongClickListener的触发条件是按下触屏且停留一段事件

onLongClick方法返回false不影响OnClickListener的触发;onLongClick方法返回true,OnClickListener不再触发

Demo代码

demo代码可以在我的github上下载:Android触屏事件传递演示Demo

相关文章

Android Touch事件传递机制(一) – onInterceptTouchEvent & onTouchEvent

Android Touch事件传递机制(三) – Touch事件分发(dispatchTouchEvent)

Android Touch事件传递机制(四) – Touch事件处理(onTouchEvent)

参考

Android onTouchEvent, onClick及onLongClick的调用机制

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有